package dao

import (
	"fmt"
	"service/app/dto"
	"service/app/mode"
	"time"
)

// 实体
// dao每次被调都都会判断实体是还存在
// 由于每个dao操作数据库,orm是必须继承
var userDao *UserDao

type UserDao struct {
	BaseDao
}

func NewUserDao() *UserDao {
	if userDao == nil {
		userDao = &UserDao{
			BaseDao: newBaseDao(),
		}
	}
	return userDao
}

/** 角色可以访问menus列表*/
func (m *UserDao) InfoUserD(roles *[]mode.Db_roles) (*[]mode.Db_menu, error) {
	// 循环角色列表里的 prem 是否与menu列表 api_id 相同
	var menulist []mode.Db_menu
	// var pm []uint
	// for _, v := range *roles {
	// 	for _, j := range v.Perm {
	// 		// 有则不添加
	// 		var exits bool
	// 		for _, k := range pm {
	// 			if k == j.ID {
	// 				exits = true
	// 			}
	// 		}
	// 		if !exits {
	// 			pm = append(pm, j.ID)
	// 		}
	// 	}
	// }
	var pm []string
	for _, v := range *roles {
		for _, j := range v.Perm {
			// 有则不添加
			var exits bool
			for _, k := range pm {
				if k == j.Fullpath {
					exits = true
				}
			}
			if !exits {
				pm = append(pm, j.Fullpath)
			}
		}
	}
	// err := m.Orm.Model(&mode.Db_menu{}).Where("api_id in ?", pm).Find(&menulist).Error
	err := m.Orm.Model(&mode.Db_menu{}).Where("path in ?", pm).Find(&menulist).Error
	if err != nil {
		return nil, err
	}
	return &menulist, nil
}

func (m *UserDao) FindUserByUsername(axUserName string, ip string) (*mode.Lz_user, error) {
	var IuserDto mode.Lz_user
	err := m.Orm.Model(&IuserDto).Where("user=?", axUserName).Find(&IuserDto).Error
	if err != nil {
		return nil, err
	}
	// 更新用户的最后登录时间
	IuserDto.Last_Login_Time = time.Now()
	IuserDto.Last_Login_Ip = ip
	err = m.Orm.Save(IuserDto).Error
	if err != nil {
		return nil, err
	}
	return &IuserDto, err
}

func (m *UserDao) FindUbyUserAndPw(axUser, axPw string) mode.Lz_user {
	var IuserDto mode.Lz_user
	m.Orm.Model(&IuserDto).Where("user=? and password=?", axUser, axPw).Find(&IuserDto)
	return IuserDto
}

func (m *UserDao) AddUser(info *dto.AdduserDto) error {
	// 将数据库模型赋值
	var IuserDto mode.Lz_user
	info.ConverToUserDao(&IuserDto)
	err := m.Orm.Create(&IuserDto)
	if err.Error == nil {
		// 返回数据给下级
		info.Id = IuserDto.ID
		info.Password = ""
		return nil
	}
	return fmt.Errorf("写入用户数据库失败!,%v", err.Error)
}

func (m *UserDao) ExistUserByName(userName string) bool {
	var Iuser mode.Lz_user
	var total int64
	m.Orm.Model(Iuser).Where("user = ?", userName).Count(&total)
	return total > 0
}

func (m *UserDao) GetUserById(id dto.ReqUriIdDto) (mode.Lz_user, error) {
	var Iuser mode.Lz_user
	return Iuser, m.Orm.First(&Iuser, id).Error
}

func (m *UserDao) PaginatUser(paginat *dto.ReqPaginat) (*[]mode.IresUserList, int64, error) {
	var UserList []mode.IresUserList
	var total int64
	// 数据库联查
	// err := m.Orm.Model(&mode.Lz_user{}).Count(&total).
	// 	Scopes(paginat.PaginatFn(m.Orm)).Find(&UserList).Error
	// // err := m.Orm.Model(&mode.Lz_user{}).Scopes(paginat.PaginatFn(m.Orm)).Find(&UserList).
	// // 	Scopes().Limit(-1).Offset(-1).Count(&total).Error
	// return UserList, total, err

	if paginat.Keyword != "" {
		// 先返回带有WHERE Total
		keyword := "%" + paginat.Keyword + "%"
		if paginat.Key == "" {
			paginat.Key = "user"
		}
		err := m.Orm.Model(&mode.Lz_user{}).Where(paginat.Key+" LIKE ?", keyword).Count(&total).
			Scopes(paginat.PaginatFn(m.Orm)).Preload("Roles").Find(&UserList).Error
		return &UserList, total, err
	} else {
		err := m.Orm.Model(&mode.Lz_user{}).Count(&total).
			Scopes(paginat.PaginatFn(m.Orm)).Preload("Roles").Find(&UserList).Error
		return &UserList, total, err
	}
}

func (m *UserDao) UpdataUser(user dto.UpdataUserDto) error {
	var Iuser mode.Lz_user
	m.Orm.First(&Iuser, user.Id)
	user.ConverToUpdata(&Iuser)

	return m.Orm.Save(&Iuser).Error
}

func (m *UserDao) DelUser(userId dto.ReqUriIdDto) error {
	return m.Orm.Model(&mode.Lz_user{}).Delete("id", userId.Id).Error
}

func (m *UserDao) UserPermD(id int) (*mode.Lz_user, error) {
	var user mode.Lz_user
	err := m.Orm.Preload("Roles.Perm").Preload("Roles").Where("id=?", id).Find(&user).Error
	if err != nil {
		return nil, err
	}
	//TAG struct中需要删除用户密码
	user.Password = ""
	return &user, nil
}
